﻿using AngleSharp.Common;
using AutoMapper;
using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WxBean.Core.IServices;
using WxBean.Core.IServices.Comic;
using WxBean.Core.Model;
using WxBean.Core.Model.ViewModels.Comic;
using WxBean.Core.Services.BASE;

namespace WxBean.Core.Services
{
    public class ComicService : BaseServices<ComicModel>, IComicService
    {
        private IWebBasicService _webBasicService;
        private readonly IMapper _mapper;
        private IComicChapterService _chapterService;
        private IComicChapterDetailService _chapterDetailService;
        public ComicService(IWebBasicService webBasicService, IMapper mapper, IComicChapterService comicChapterService, IComicChapterDetailService chapterDetailService)
        {
            _webBasicService = webBasicService;
            _chapterService = comicChapterService;
            _mapper = mapper;
            _chapterDetailService = chapterDetailService;
        }
        /// <summary>
        /// 查询漫画
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<MessageModel<IEnumerable<ComicSearch>>> SearchAsync(string name)
        {
            var comicSearchList = new List<ComicSearch>();

            var comicModelDtoList = new List<ComicModelDto>();
            // 先查询数据库中是否存在数据 数据来源于那个网站
            var comicList = await Query(q => q.Name == name && q.Status == Model.Enum.ComicStatus.Completed);
            if (comicList?.Any() ?? true)
            {
              var comicSearch = comicList.Select(s => new ComicSearch
                {
                    Name = s.Name,
                    CoverUrl = s.CoverUrl,
                    LastUpdate = s.LastUpdate,
                    Author = s.Author,
                    LastChapterName = s.LastChapterName,
                    LastNumber = s.LastNumber,
                    LastUpdateTime = s.LastUpdateTime,
                    Status = s.Status,
                    Url = s.Url,
                    UpdateTo = s.LastUpdate,
                    Source = s.Source,
                });
                return MessageModel<IEnumerable<ComicSearch>>.Message(true, "成功", comicSearch);
            }
            try
            {
                comicModelDtoList = await CrawlingComicAsync(name);

                if (!comicModelDtoList?.Any() ?? true)
                {
                    return MessageModel<IEnumerable<ComicSearch>>.Message(true, "暂无结果", null);
                }
                //var conCurrentTask = new ConcurrentTask(comicModelDtoList.Count());
                _ = Task.Run(() =>
                {
                    foreach (var item in comicModelDtoList)
                    {
                        _ = ExecteAddAsync(item);
                        //_ = conCurrentTask.RunAsync(() => );
                    }
                });

                comicSearchList = comicModelDtoList.Select(s => new ComicSearch
                {
                    Name = s.Name,
                    CoverUrl = s.CoverUrl,
                    LastUpdate = s.LastUpdate,
                    Author = s.Author,
                    LastChapterName = s.LastChapterName,
                    LastNumber = s.LastNumber,
                    LastUpdateTime = s.LastUpdateTime,
                    Status = s.Status,
                    Url = s.Url,
                    UpdateTo = s.LastUpdate,
                    Source = s.Source,
                }).ToList();


            }
            catch (Exception ex)
            {
                await Console.Out.WriteLineAsync(ex.Message);
            }

            return MessageModel<IEnumerable<ComicSearch>>.Success("", comicSearchList);

        }

        /// <summary>
        /// 执行数据库操作
        /// </summary>
        /// <returns></returns>
        private async Task ExecteAddAsync(ComicModelDto model)
        {
            var comic = _mapper.Map<ComicModel>(model);

            // 判断数据库中是否存在该数据 存在就更新最新章节  不存在就添加到数据库中
            var comicDataBase = (await Query(q => q.Name == model.Name)).FirstOrDefault();

            if (comicDataBase == null)
            {
                var comicId = await Add(comic);
                if (!model.ChpterList?.Any() ?? true)
                {
                    return;
                }
                var conCurrentTask = new ConcurrentTask(1);
                //var conCurrentTask = new ConcurrentTask(model.ChpterList.Count());
                foreach (var chapter in model.ChpterList)
                {

                    await conCurrentTask.RunAsync(async () => await ExecuteAddChapterAsync(chapter, comicId));
                }

                await conCurrentTask.WaitTaskCompltedAsync();
            }
            else
            {
                var chapterList = await _chapterService.Query(q => q.ComicId == comicDataBase.Id);
                //var chapterModel = _mapper.Map<List<ComicChapter>>(model.ChpterList);
                if (model.LastUpdate != comicDataBase.LastUpdate)
                {
                    comicDataBase.UpdateTime = DateTime.Now;
                    comicDataBase.LastUpdate = model.LastUpdate;
                    comicDataBase.LastNumber = model.LastNumber;
                    comicDataBase.LastChapterName = model.LastChapterName;
                    comicDataBase.LastUpdateTime = comicDataBase.LastUpdateTime;

                    await Update(comicDataBase);

                    if (!model.ChpterList?.Any() ?? true)
                    {
                        return;
                    }
                    var conCurrentTask = new ConcurrentTask(model.ChpterList.Count());
                    foreach (var chapter in model.ChpterList)
                    {
                        if (chapterList.Select(s => s.Name).Contains(chapter.Name) && chapterList.Select(s => s.Number).Contains(chapter.Number))
                        {
                            continue;
                        }

                        await conCurrentTask.RunAsync(async () => await ExecuteAddChapterAsync(chapter, comicDataBase.Id));
                    }


                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private async Task ExecuteAddChapterAsync(ComicChapterDto chapter, long comicId)
        {
            try
            {
                var chapterModel = _mapper.Map<ComicChapter>(chapter);
                chapterModel.ComicId = comicId;
                var chapterId = await _chapterService.Add(chapterModel);

                var detailList = new List<ComicChapterDetail>();

                if (!chapter.ChapterDetailList?.Any() ?? true)
                {
                    return;
                }

                foreach (var detailItem in chapter.ChapterDetailList)
                {
                    var detail = _mapper.Map<ComicChapterDetail>(detailItem);
                    detail.ChapterId = chapterId;
                    detail.CreateTime = DateTime.Now;
                    detail.UpdateTime = DateTime.Now;
                    //var id = await _chapterDetailService.Add(detail);
                    detailList.Add(detail);
                }

                var id = await _chapterDetailService.Add(detailList);
            }
            catch (Exception ex)
            {
                await Console.Out.WriteLineAsync(ex.Message);
                throw;
            }


        }

        /// <summary>
        /// 爬取漫画方法
        /// </summary>
        /// <returns></returns>
        private async Task<List<ComicModelDto>> CrawlingComicAsync(string name)
        {
            var comicList = new List<ComicModelDto>();
            try
            {
                var comicSearchList = new List<ComicSearch>();
                var taskList = new List<Task<IEnumerable<ComicModelDto>>>();
                var webList = await _webBasicService.Query(q => q.Action && q.WebType == WebSiteType.Comic);
                var dic = webList.ToDictionary(t => t.Name, m => m);
                if (!webList?.Any() ?? true)
                {
                    return new List<ComicModelDto>();
                }

                foreach (var item in webList)
                {
                    var task = ComicFactory.CreateComicAsync(item.ComicType)?.ExecuteAsync(item, name);
                    if (task == null)
                    {
                        continue;
                    }
                    taskList.Add(task);
                }

                await Task.WhenAll(taskList);
                comicList = taskList.SelectMany(j => j.ConfigureAwait(false).GetAwaiter().GetResult())?.ToList();
            }
            catch (Exception ex)
            {
                await Console.Out.WriteLineAsync(ex.Message);
                throw;
            }


            return comicList;
        }

    }
}
